﻿@using Gurux.DLMS.AMI.Client.Pages.User;
@using Gurux.DLMS.AMI.Shared.DIs
@using Gurux.DLMS.AMI.Shared.DTOs.KeyManagement;
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Gurux.DLMS.AMI.Shared.DTOs
@using Gurux.DLMS.AMI.Shared.DTOs.Authentication
@using Gurux.DLMS.AMI.Shared.Rest
@using Microsoft.AspNetCore.SignalR.Client
@using Gurux.DLMS.AMI.Shared
@using Gurux.DLMS.AMI.Shared.Enums
@using Gurux.DLMS.AMI.Client.Helpers
@using Gurux.DLMS.AMI.Module
@using System.Linq

@inject HttpClient Http
@inject IGXNotifier Notifier

<SelectionContainer TItem="GXKeyManagementGroup" @ref="@_selectionContainer">
    <SelectionList Title="Selected" @ref="_selected"
                   ShowAllUsers="false"
                   ItemsProvider="@GetSelectedItems">
        <DataContent>
            @context.Name
        </DataContent>
        <FilterContent>
            <Search Placeholder="@Properties.Resources.FilterByName"
                    OnClickAsync="@SearchSelectedByName" />
        </FilterContent>
    </SelectionList>
    <SelectionList Title="Available" @ref="_available"
                   ItemsProvider="@GetItems">
        <DataContent>
            @context.Name
        </DataContent>
        <FilterContent>
            <Search Placeholder="@Properties.Resources.FilterByName"
                    OnClickAsync="@SearchByName" />
            <Search Placeholder="@Properties.Resources.FilterByUser"
                    OnClickAsync="@SearchByUser" />
        </FilterContent>
    </SelectionList>
</SelectionContainer>

@code {
    [CascadingParameter]
    private UserGroupTab? UserGroupParent { get; set; }

    [CascadingParameter]
    private KeyManagementTab? KeyManagementParent { get; set; }

    SelectionList<GXKeyManagementGroup>? _selected;
    SelectionList<GXKeyManagementGroup>? _available;
    SelectionContainer<GXKeyManagementGroup>? _selectionContainer;

    /// <summary>
    /// KeyManagement group filter.
    /// </summary>
    private GXKeyManagementGroup filter = new GXKeyManagementGroup(null);

    protected async Task SearchSelectedByName(string? name)
    {
        try
        {
            if (_selected?.Items != null)
            {
                _selected.HiddenItems.Clear();
                if (!string.IsNullOrEmpty(name))
                {
                    name = name.ToLower();
                    foreach (var it in _selected.Items)
                    {
                        if (it.Name != null && !it.Name.ToLower().Contains(name))
                        {
                            _selected.HiddenItems.Add(it);
                        }
                    }
                }
                Notifier?.ClearStatus();
                await _selected.RefreshDataAsync();
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    protected async Task SearchByName(string? name)
    {
        try
        {
            if (_available != null)
            {
                filter.Name = name;
                Notifier?.ClearStatus();
                await _available.RefreshDataAsync();
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    protected async Task SearchByUser(string? userName)
    {
        try
        {
            if (_available != null)
            {
                if (string.IsNullOrEmpty(userName))
                {
                    filter.UserGroups = null;
                }
                else
                {
                    GXUser user;
                    GXUserGroup? ug = filter.UserGroups?.FirstOrDefault();
                    if (ug == null)
                    {
                        user = new GXUser();
                        ug = new GXUserGroup();
                        filter.UserGroups = new(new GXUserGroup[] { ug });
                        ug.Users = new(new GXUser[] { user });
                    }
                    else
                    {
                        user = filter.UserGroups[0].Users[0];
                    }
                    user.UserName = userName;
                }
                Notifier?.ClearStatus();
                await _available.RefreshDataAsync();
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    /// <summary>
    /// Filter is done when SearchSelectedByName is called.
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    private ValueTask<ItemsProviderResult<GXKeyManagementGroup>> GetSelectedItems(GXItemsProviderRequest request)
    {
        if (_selected?.Items == null)
        {
            return default;
        }
        //ToArray makes a clone from the items. Don't remove it.
        return new(new ItemsProviderResult<GXKeyManagementGroup>(_selected.Items.ToArray(), _selected.Items.Count));
    }

    private async ValueTask<ItemsProviderResult<GXKeyManagementGroup>> GetItems(GXItemsProviderRequest request)
    {
        //Don't clear status or error is lost.
        Notifier?.ProgressStart();
        try
        {
            ListKeyManagementGroups req = new ListKeyManagementGroups()
                {
                    Index = request.StartIndex,
                    Count = request.Count,
                    Filter = filter,
                    Descending = request.Descending,
                    AllUsers = request.ShowAllUserData,
                    Exclude = _selected?.Items?.Select(s => s.Id).ToArray()
                };
            var ret = await Http.PostAsJson<ListKeyManagementGroupsResponse>("api/KeyManagementGroup/List", req, request.CancellationToken);
            if (ret?.KeyManagementGroups != null && _selected != null)
            {
                return new ItemsProviderResult<GXKeyManagementGroup>(ret.KeyManagementGroups, ret.Count);
            }
        }
        catch (TaskCanceledException)
        {
            //Let the table component handle this.
            throw;
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
        finally
        {
            Notifier?.ProgressEnd();
        }
        return default;
    }

    protected override async Task OnInitializedAsync()
    {
        //Wait until table is loaded. Don't remove this or selector is null.
        await Task.Delay(1);
        try
        {
            if (_selectionContainer == null || _selected == null)
            {
                throw new ArgumentException(Properties.Resources.InvalidTarget);
            }
            Notifier.ProgressStart();
            Notifier.ClearStatus();
            CrudAction action;
            if (UserGroupParent?.Active?.KeyManagementGroups != null)
            {
                //Add selected key managements.
                _selected.Items = UserGroupParent.Active.KeyManagementGroups;
                action = ClientHelpers.GetAction(UserGroupParent.Action);
            }
            else if (KeyManagementParent?.Active?.KeyManagementGroups != null)
            {
                //Add selected key managements.
                _selected.Items = KeyManagementParent.Active.KeyManagementGroups;
                action = ClientHelpers.GetAction(KeyManagementParent.Action);
            }
            else
            {
                throw new ArgumentException(Properties.Resources.InvalidTarget);
            }
            bool addDefaultGroups = action == CrudAction.Create && !_selected.Items.Any();
            if (addDefaultGroups)
            {
                //Show default groups when new group is added.
                ListKeyManagementGroups req = new ListKeyManagementGroups()
                    {
                        Filter = new GXKeyManagementGroup()
                        {
                            Default = true
                        },
                        Count = _selectionContainer.PageSize,
                        Exclude = _selected.Items.Select(s => s.Id).ToArray()
                    };
                var ret = await Http.PostAsJson<ListKeyManagementGroupsResponse>("api/KeyManagementGroup/List", req);
                if (ret?.KeyManagementGroups != null)
                {
                    _selected.Items.AddRange(ret.KeyManagementGroups);
                }
            }
            //Read available items.
            if (_available != null)
            {
                await _available.RefreshDataAsync();
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
        finally
        {
            Notifier?.ProgressEnd();
        }
    }
}

